Skip to content

feat(testing): cut over daily test suite to Kueue scheduling - #6014

Draft
sudheer-quad wants to merge 3 commits into
GoogleCloudPlatform:developfrom
sudheer-quad:feature/kueue-migration-daily-tests
Draft

feat(testing): cut over daily test suite to Kueue scheduling#6014
sudheer-quad wants to merge 3 commits into
GoogleCloudPlatform:developfrom
sudheer-quad:feature/kueue-migration-daily-tests

Conversation

@sudheer-quad

Copy link
Copy Markdown
Contributor

This PR transitions the slurm-gcp-v6-rocky-8 daily test suite to Kueue scheduling in the hpc-toolkit-dev-2 project.

Submission Checklist

NOTE: Community submissions can take up to 2 weeks to be reviewed.

Please take the following actions before submitting this pull request.

  • Fork your PR branch from the Toolkit "develop" branch (not main)
  • Test all changes with pre-commit in a local branch #
  • Confirm that "make tests" passes all tests
  • Add or modify unit tests to cover code changes
  • Ensure that unit test coverage remains above 80%
  • Update all applicable documentation
  • Follow Cluster Toolkit Contribution guidelines #

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request migrates the slurm-gcp-v6-rocky-8 daily test suite to use Kueue for job scheduling within the hpc-toolkit-dev-2 project. The changes involve replacing the legacy build process with a containerized job execution model that leverages Kueue for queue management, retry logic, and better resource utilization. Additionally, the infrastructure code has been updated to support these new triggers and scheduling requirements.

Highlights

  • Kueue Migration: Transitioned the slurm-gcp-v6-rocky-8 daily test suite to use Kueue scheduling for improved resource management.
  • Infrastructure Updates: Added new helper scripts for monitoring Kueue jobs, checking for retriable errors, and handling zone capacity retries.
  • Terraform Configuration: Updated infrastructure provisioning to support the migrated test suite, including new triggers and scheduling configurations.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions Bot added the external PR from external contributor label Jul 28, 2026
@sudheer-quad sudheer-quad self-assigned this Jul 28, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the slurm-gcp-v6-rocky8 daily integration test to run as a GKE Kueue job, introducing scripts to monitor Kueue jobs, wait for zone capacity, and check for retriable errors, alongside updating the Terraform provisioning configurations. Feedback on these changes highlights several issues: missing secret environment variables in the job manifest generation step, a lack of file existence verification in the retriable error check script, a missing set -e inside the subshell of the zone availability script, and the potential for the newly added backup file slurm-gcp-v6-rocky8_old.yaml to be accidentally discovered and scheduled by automated test scripts.

Comment thread tools/cloud-build/daily-tests/builds/slurm-gcp-v6-rocky8.yaml Outdated
Comment thread tools/cloud-build/check_retriable_error.sh
Comment thread tools/cloud-build/wait_for_available_zone.sh
Comment thread tools/cloud-build/daily-tests/builds/slurm-gcp-v6-rocky8_old.yaml
@sudheer-quad
sudheer-quad force-pushed the feature/kueue-migration-daily-tests branch 5 times, most recently from 2deff8a to e7e6910 Compare July 28, 2026 12:24
@sudheer-quad
sudheer-quad force-pushed the feature/kueue-migration-daily-tests branch from e7e6910 to cb9ad7f Compare July 28, 2026 13:07
@sudheer-quad

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the daily integration tests (specifically slurm-gcp-v6-rocky8) to run on GKE Kueue. It introduces new scripts to monitor Kueue jobs, check for retriable errors, and wait for available zones, alongside updating the Terraform provisioning configuration. The review feedback identifies several critical improvements: preventing duplicate triggers by filtering out migrated tests from the old schedule, adding a timeout to the pod initialization loop in monitor_kueue_job.sh to prevent pipeline hangs, handling external job deletion gracefully, removing a backup YAML file that could clutter test discovery, and using mktemp instead of static paths in /tmp to avoid file conflicts.

Comment on lines +49 to +53
resource "google_cloudbuild_trigger" "daily_test_migrated" {
for_each = toset(var.kueue_migrated_tests)
name = "DAILY-test-${each.key}"
project = var.daily_tests_project_id
tags = [local.notify_chat_tag]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The original daily_test trigger and schedule in daily-tests.tf must be filtered to exclude var.kueue_migrated_tests to prevent duplicate triggers from being created and run in the old project. Currently, both the old and new triggers will be created for slurm-gcp-v6-rocky8 because list_tests_midnight still returns it.

Comment on lines +47 to +58
while true; do
POD_NAME=$(kubectl get pods -n "$NAMESPACE" --selector=job-name="$JOB_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
if [ -n "$POD_NAME" ]; then
POD_PHASE=$(kubectl get pod "$POD_NAME" -n "$NAMESPACE" -o jsonpath='{.status.phase}' 2>/dev/null)
if [ "$POD_PHASE" = "Running" ] || [ "$POD_PHASE" = "Succeeded" ] || [ "$POD_PHASE" = "Failed" ]; then
echo "Pod $POD_NAME is $POD_PHASE. Ready to stream logs."
break
fi
echo "Pod $POD_NAME detected but is in phase: $POD_PHASE. Waiting for it to start running..."
fi
sleep 5
done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If the GKE job fails to schedule or encounters a terminal error (such as ImagePullBackOff or invalid service account), the pod may remain in Pending or another non-running phase indefinitely. Since there is no timeout in this loop, the Cloud Build pipeline will hang until the 24-hour timeout is reached, incurring significant costs. Consider adding a reasonable timeout (e.g., 20 minutes) to this loop.

Suggested change
while true; do
POD_NAME=$(kubectl get pods -n "$NAMESPACE" --selector=job-name="$JOB_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
if [ -n "$POD_NAME" ]; then
POD_PHASE=$(kubectl get pod "$POD_NAME" -n "$NAMESPACE" -o jsonpath='{.status.phase}' 2>/dev/null)
if [ "$POD_PHASE" = "Running" ] || [ "$POD_PHASE" = "Succeeded" ] || [ "$POD_PHASE" = "Failed" ]; then
echo "Pod $POD_NAME is $POD_PHASE. Ready to stream logs."
break
fi
echo "Pod $POD_NAME detected but is in phase: $POD_PHASE. Waiting for it to start running..."
fi
sleep 5
done
POD_INIT_TIMEOUT=1200
START_TIME=$SECONDS
while true; do
if [ $((SECONDS - START_TIME)) -gt $POD_INIT_TIMEOUT ]; then
echo "Error: Pod initialization timed out after 20 minutes." >&2
exit 1
fi
POD_NAME=$(kubectl get pods -n "$NAMESPACE" --selector=job-name="$JOB_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
if [ -n "$POD_NAME" ]; then
POD_PHASE=$(kubectl get pod "$POD_NAME" -n "$NAMESPACE" -o jsonpath='{.status.phase}' 2>/dev/null)
if [ "$POD_PHASE" = "Running" ] || [ "$POD_PHASE" = "Succeeded" ] || [ "$POD_PHASE" = "Failed" ]; then
echo "Pod $POD_NAME is $POD_PHASE. Ready to stream logs."
break
fi
echo "Pod $POD_NAME detected but is in phase: $POD_PHASE. Waiting for it to start running..."
fi
sleep 5
done

Comment on lines +70 to +75
SUCCEEDED=$(kubectl get job "$JOB_NAME" -n "$NAMESPACE" -o jsonpath='{.status.succeeded}' 2>/dev/null)
FAILED=$(kubectl get job "$JOB_NAME" -n "$NAMESPACE" -o jsonpath='{.status.failed}' 2>/dev/null)

if [ "$SUCCEEDED" = "1" ] || [ "$FAILED" = "1" ]; then
break
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If the GKE job is deleted externally (e.g., by an administrator or another process), kubectl get job will fail and return a non-zero exit code, leaving both SUCCEEDED and FAILED empty. This will cause the loop to print "Logs disconnected but job is not finished. Reconnecting..." and loop infinitely. Check the exit status of kubectl get job to handle deletion gracefully.

Suggested change
SUCCEEDED=$(kubectl get job "$JOB_NAME" -n "$NAMESPACE" -o jsonpath='{.status.succeeded}' 2>/dev/null)
FAILED=$(kubectl get job "$JOB_NAME" -n "$NAMESPACE" -o jsonpath='{.status.failed}' 2>/dev/null)
if [ "$SUCCEEDED" = "1" ] || [ "$FAILED" = "1" ]; then
break
fi
if ! JOB_STATUS=$(kubectl get job "$JOB_NAME" -n "$NAMESPACE" -o jsonpath='{.status.succeeded}{" "}{.status.failed}' 2>/dev/null); then
echo "Error: Job $JOB_NAME no longer exists or kubectl failed. Exiting." >&2
exit 1
fi
read -r SUCCEEDED FAILED <<< "$JOB_STATUS"
if [ "$SUCCEEDED" = "1" ] || [ "$FAILED" = "1" ]; then
break
fi

@@ -0,0 +1,76 @@
# Copyright 2026 Google LLC

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This backup file slurm-gcp-v6-rocky8_old.yaml should be removed from the repository. Keeping old/backup versions of files clutters the codebase and can cause issues with automated test discovery tools (like list_tests_midnight) which might scan all YAML files in this directory and attempt to provision duplicate triggers.

Comment on lines +19 to +47
while true; do
# Run the script in a subshell, streaming stdout and stderr to the console and a log file.
# To extract the exported variables, we have the subshell write them to a file.
set +e
(
set -e
source /workspace/tools/cloud-build/find_available_zone.sh
# If it succeeds, these lines will execute and save the exports.
echo "export ZONE=\"${ZONE}\"" >/tmp/zone_export.sh
echo "export PROVISIONING_MODEL=\"${PROVISIONING_MODEL}\"" >>/tmp/zone_export.sh
) 2>&1 | tee /tmp/zone_output.log

EXIT_CODE=${PIPESTATUS[0]}
set -e

if [ "$EXIT_CODE" -eq 0 ]; then
source /tmp/zone_export.sh
break
else
# Check if the failure was specifically due to zone capacity
if grep -q "Couldn't find a zone to deploy" /tmp/zone_output.log; then
echo "--- RETRYING in 5 minutes... ---" >&2
sleep 300
else
echo "--- FATAL ERROR: find_available_zone.sh failed due to a configuration or system error. Exiting. ---" >&2
exit 1
fi
fi
done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using static file paths in /tmp (like /tmp/zone_export.sh and /tmp/zone_output.log) can lead to conflicts or security issues if multiple processes run in the same environment. Use mktemp to generate unique temporary files and ensure they are cleaned up on exit.

ZONE_EXPORT=$(mktemp)
ZONE_OUTPUT=$(mktemp)
trap 'rm -f "$ZONE_EXPORT" "$ZONE_OUTPUT"' EXIT

while true; do
	# Run the script in a subshell, streaming stdout and stderr to the console and a log file.
	# To extract the exported variables, we have the subshell write them to a file.
	set +e
	(
		set -e
		source /workspace/tools/cloud-build/find_available_zone.sh
		# If it succeeds, these lines will execute and save the exports.
		echo "export ZONE=\"${ZONE}\"" >"$ZONE_EXPORT"
		echo "export PROVISIONING_MODEL=\"${PROVISIONING_MODEL}\"" >>"$ZONE_EXPORT"
	) 2>&1 | tee "$ZONE_OUTPUT"

	EXIT_CODE=${PIPESTATUS[0]}
	set -e

	if [ "$EXIT_CODE" -eq 0 ]; then
		source "$ZONE_EXPORT"
		break
	else
		# Check if the failure was specifically due to zone capacity
		if grep -q "Couldn't find a zone to deploy" "$ZONE_OUTPUT"; then
			echo "--- RETRYING in 5 minutes... ---" >&2
			sleep 300
		else
			echo "--- FATAL ERROR: find_available_zone.sh failed due to a configuration or system error. Exiting. ---" >&2
			exit 1
		fi
	fi
done
References
  1. In shell scripts, avoid creating temporary directories or files in /tmp with predictable names. Prefer using mktemp for secure temporary creation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external PR from external contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant